﻿using System;
using System.Collections.Generic;
using System.Linq;
using BusinessBingo.Data.DataOrderOptions;
using BusinessBingo.Data.Filter;
using BusinessBingo.Data.Interfaces;
using BusinessBingo.Model;
using BusinessBingo.Model.Interfaces;
using BusinessBingo.Queries;
using BusinessBingo.QueryHandlers.Base;
using BusinessBingo.QueryHandlers.Interfaces;
using BusinessBingo.QueryHandlers.Results;

namespace BusinessBingo.QueryHandlers
{
    public class GetRandomBingoSetQueryHandler :
        BaseQueryHandler,
        IGetRandomBingoSetQueryHandler
    { 
        private IWordRepository _wordRepository;

        public GetRandomBingoSetQueryHandler(IValidationState validationState, 
                                      IWordRepository wordRepository) : base(validationState)
        {
            this._wordRepository = wordRepository;
        }

        public GetRandomBingoSetQueryHandlerResult Execute(GetRandomBingoSetQuery getRandomBingoSetQuery)
        {
            GetRandomBingoSetQueryHandlerResult result = new GetRandomBingoSetQueryHandlerResult();

            if(getRandomBingoSetQuery == default(GetRandomBingoSetQuery))
                throw new ArgumentNullException("GetRandomBingoSetQuery");

            if (getRandomBingoSetQuery.Size == 0)
                this._validationState.AddError<GetRandomBingoSetQuery>(x => x.Size, ErrorTypes.Invalid);

            if (this._validationState.IsValid == false) return result;

            WordFilter filter = new WordFilter();
            filter.NumberOfWords = getRandomBingoSetQuery.Size * getRandomBingoSetQuery.Size;
            filter.WithLanguage = getRandomBingoSetQuery.Language;

            WordDataOrderOptions doo = new WordDataOrderOptions();
            doo.OrderType = DataOrderTypes.Random;

            IList<Word> words = this._wordRepository.GetItems(null, doo, filter).ToList();

            BingoSet bingoSet = new BingoSet();
            bingoSet.Size = getRandomBingoSetQuery.Size;

            for (int x = 0; x < bingoSet.Size; x++)
            {
                for (int y = 0; y < bingoSet.Size; y++)
                {
                    WordPosition wordPosition = new WordPosition();
                    wordPosition.PositionX = x;
                    wordPosition.PositionY = y;

                    wordPosition.Word = words.First();
                    words.Remove(wordPosition.Word);

                    bingoSet.WordPositions.Add(wordPosition);
                }
            }

            bingoSet.WordPositions = bingoSet.WordPositions.OrderBy(x => x.PositionX).ThenBy(x => x.PositionY).ToList();

            result.BingoSet = bingoSet;
            result.Succeeded = true;

            return result;
        }
    }
}